Cypress 简介
Cypress 是一个面向现代 Web 应用的端到端测试框架。与单元测试不同,E2E 测试模拟用户在浏览器中的真实操作流程,包括页面跳转、按钮点击、表单输入与提交等完整链路。
E2E 测试与单元测试的区别
| 维度 | 单元测试 | E2E 测试 |
|---|---|---|
| 测试范围 | 单个组件或函数 | 完整用户流程 |
| 运行环境 | jsdom(模拟 DOM) | 真实浏览器 |
| 速度 | 快(毫秒级) | 慢(秒级) |
| 关注点 | Props、事件、渲染逻辑 | 交互、路由、数据流 |
| 工具 | Vitest + Vue Test Utils | Cypress / Playwright |
Cypress 的核心能力:
- 完整模拟浏览器环境,加载路由并执行页面跳转
- 测试用户点击、输入、表单提交等操作
- 生成完整的测试报告(错误时间、错误内容、执行时长)
- 支持 CI/CD 工具通过命令行执行
- 自动重试失败的测试用例
安装 Cypress
# 推荐使用 cnpm(大体积包网络更稳定)
cnpm install cypress -D
# 或使用 pnpm
pnpm add -D cypress
bash
Cypress 包含一个完整的浏览器内核,安装包体积较大。500M 宽带下载约 26 秒(供参考)。如果网络条件好,使用 pnpm 或 npm 安装同样可行。
:::
安装后添加测试命令:
{
"scripts": {
"test:e2e": "cypress run",
"test:e2e:dev": "cypress open"
}
}
json
启动与运行
# 交互模式(带可视化界面)
pnpm test:e2e:dev
bash
启动后:
- 选择浏览器(推荐 Chrome,也可选 Electron)
- 点击 "Start Testing in Chrome"
- 选择测试文件运行
默认超时行为
cy.visit() 默认等待页面触发 load 事件。如果页面加载超过 60 秒,Cypress 会自动报错。
Cypress 核心概念
1. Actions(用户操作)
Cypress 通过 Actions API 模拟用户操作:
| Action | 说明 |
|---|---|
.click() | 单击元素 |
.dblclick() | 双击 |
.rightclick() | 右击 |
.type(text) | 模拟键盘输入 |
.check() | 勾选 checkbox/radio |
.uncheck() | 取消勾选 |
.select(value) | 选择下拉选项 |
.selectFile(path) | 上传文件 |
.scrollIntoView() | 滚动到元素可见 |
.trigger(event) | 触发原生事件(focus、mousedown 等) |
.scrollTo(position) | 滚动到指定位置 |
2. Queries(元素查询)
定位页面元素的核心方法:
| Query | 说明 |
|---|---|
cy.get(selector) | 通过 CSS 选择器获取元素(类似 jQuery 的 $()) |
cy.contains(text) | 获取包含指定文本的元素 |
.children() | 获取子元素 |
.parent() | 获取父元素 |
.siblings() | 获取兄弟元素 |
.next() | 获取下一个兄弟元素 |
.prev() | 获取上一个兄弟元素 |
.find(selector) | 在后代中查找元素 |
.first() | 获取第一个匹配元素 |
.last() | 获取最后一个匹配元素 |
最常用的是 cy.get() 和 cy.contains()。
3. Assertions(断言)
使用 .should() 方法进行断言,底层基于 Chai 断言库:
// 断言文本内容
cy.get('h1').should('have.text', 'Hello')
// 断言元素数量
cy.get('.item').should('have.length', 3)
// 断言 class
cy.get('.tab').should('have.class', 'active')
// 断言属性
cy.get('a').should('have.attr', 'href', '/about')
cy.get('a').should('have.attr', 'target', '_blank')
// 否定断言
cy.get('.modal').should('not.be.visible')
// 常用简写
cy.get('.count').should('eq', '5') // 等同于 have.text
cy.get('.item').should('not.eq', '0')
javascript
断言方法对照
| Cypress 写法 | Chai 写法 |
|---|---|
.should('have.text', 'Hello') | expect(el.text()).to.equal('Hello') |
.should('have.length', 3) | expect(els).to.have.length(3) |
.should('have.class', 'active') | expect(el.classes()).to.include('active') |
.should('eq', value) | expect(val).to.equal(value) |
.should('not.eq', value) | expect(val).to.not.equal(value) |
4. Navigation(导航)
| 命令 | 说明 |
|---|---|
cy.visit(url) | 访问指定页面 |
cy.go('back') | 浏览器后退 |
cy.go('forward') | 浏览器前进 |
cy.go(-2) | 后退两步 |
cy.reload() | 重新加载页面 |
cy.visit('/') // 访问首页
cy.go('back') // 后退
cy.go(-2) // 后退两步
cy.reload() // 刷新
javascript
测试文件结构
Cypress 测试文件与单元测试结构相似:
describe('Todo App', () => {
beforeEach(() => {
cy.visit('/') // 每个用例执行前访问页面
})
it('displays two todo items by default', () => {
cy.get('.todo-list li').should('have.length', 2)
})
it('can add new todo items', () => {
cy.get('[data-test=new-todo]').type('Feed the cat{enter}')
cy.get('.todo-list li').should('have.length', 3)
cy.get('.todo-list li').last().should('have.text', 'Feed the cat')
})
})
javascript
Cypress 自带示例
Cypress 安装后在 cypress/e2e/ 目录下提供了丰富的官方示例,涵盖:
- Getting Started — 基础入门示例
- Todo MVC — 完整的 Todo 应用测试(增删改查)
- Advanced — 进阶测试场景
- Navigation — 路由导航测试
- Location — URL 和路由状态测试
- Actions — 各种用户交互操作
学习 Cypress API 的方法
- 确定用户操作 — 左侧 Actions 面板查看
click、type、select等操作方法 - 查询元素 — 左侧 Queries 面板查看
get、contains、find等定位方法 - 编写断言 — 使用
.should()结合 Chai 断言库进行验证 - 搜索文档 — 按
Cmd+K或点击搜索框,输入关键词查找 API
TypeScript 支持
使用 TypeScript 时,.should() 方法会提供类型提示。只需明确要判断的是"类型"还是"值",就能找到对应的断言方法。
↑